#include "napi/native_api.h"
#include "hilog/log.h"
#include <arkui/native_interface.h>
#include <arkui/native_node.h>
#include <arkui/native_type.h>
#include <arkui/native_node_napi.h>
#include <arkui/native_gesture.h>
#include <arkui/native_dialog.h>
#include "hitrace/trace.h"


#include <cmath>
#include <cstdlib>
#include <native_drawing/drawing_text_declaration.h>
#include <native_drawing/drawing_text_typography.h>
#include <native_drawing/drawing_font_collection.h>
#include <sstream>

typedef struct {
  ArkUI_NativeNodeAPI_1 *nodeAPI;
  ArkUI_NativeGestureAPI_1 *gestureAPI;
  ArkUI_NativeDialogAPI_1 *dialogAPI;
} ArkUIAPIHelper;

static ArkUIAPIHelper* getAPIHelper() {
  static ArkUIAPIHelper* helper = new ArkUIAPIHelper();
  if (!helper->gestureAPI) {
    OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_GESTURE, ArkUI_NativeGestureAPI_1, helper->gestureAPI);
  }
  if (!helper->nodeAPI) {
    OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_NODE, ArkUI_NativeNodeAPI_1, helper->nodeAPI);
  }
  if (!helper->dialogAPI) {
    OH_ArkUI_GetModuleInterface(ARKUI_NATIVE_DIALOG, ArkUI_NativeDialogAPI_1, helper->dialogAPI);
  }
  return helper; 
}

static napi_value Add(napi_env env, napi_callback_info info) {
  size_t requireArgc = 2;
  size_t argc = 2;
  napi_value args[2] = {nullptr};

  napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

  napi_valuetype valuetype0;
  napi_typeof(env, args[0], &valuetype0);

  napi_valuetype valuetype1;
  napi_typeof(env, args[1], &valuetype1);

  double value0;
  napi_get_value_double(env, args[0], &value0);

  double value1;
  napi_get_value_double(env, args[1], &value1);

  napi_value sum;
  napi_create_double(env, value0 + value1, &sum);

//  auto api = OH_ArkUI_GetNativeAPI(ARKUI_NATIVE_NODE, 1);
//  OH_LOG_Print(LOG_APP, LogLevel::LOG_ERROR, 0, "MIST-SDK", "ark ui apihandle=%{public}p", api);

  return sum;
}


const char *GetStringChars(napi_env env, napi_value arg, char *c) {
  napi_status status;
  size_t length;
  status = napi_get_value_string_utf8(env, arg, nullptr, 0, &length);
  if (status != napi_ok) {
    //    MUS_ASSERT(false);
    return nullptr;
  }

  size_t copied_len;
  //  std::vector<char> buff(length + 1);
  //  status = napi_get_value_string_utf8(env, arg, static_cast<char *>(buff.data()), buff.size(), &copied_len);
  c = (char *)malloc(sizeof(char) * (length + 1));
  status = napi_get_value_string_utf8(env, arg, c, length + 1, &copied_len);

  if (status != napi_ok) {
    //    MUS_ASSERT(false);
    return nullptr;
  }

  return c;
}


static napi_value measureText(napi_env env, napi_callback_info info) {
  size_t argc = 1;
  napi_value args[1] = {nullptr};
  napi_status st = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

  bool isArray = false;
  st = napi_is_array(env, args[0], &isArray);
  if (isArray) {
    uint32_t len;
    st = napi_get_array_length(env, args[0], &len);

    auto typographyStyle = OH_Drawing_CreateTypographyStyle();
    auto fontCollection = OH_Drawing_CreateFontCollection();
    auto typographyHandler = OH_Drawing_CreateTypographyHandler(typographyStyle, fontCollection);

    for (size_t i = 0; i < len; i++) {
      napi_value element;
      st = napi_get_element(env, args[0], i, &element);
      auto buf = GetStringChars(env, element, nullptr);
      auto style = OH_Drawing_CreateTextStyle();
      // font
      // font-size
      OH_Drawing_SetTextStyleFontSize(style, 14);
      // font-style
      OH_Drawing_SetTextStyleFontStyle(style, FONT_STYLE_NORMAL);
      OH_Drawing_SetTextStyleFontWeight(style, FONT_WEIGHT_700);
      // line-spacing

      OH_Drawing_TypographyHandlerPushTextStyle(typographyHandler, style);
      OH_Drawing_TypographyHandlerAddText(typographyHandler, buf);
      OH_Drawing_TypographyHandlerPopTextStyle(typographyHandler);

//       OH_Drawing_DestroyTypography(typography);
//       OH_Drawing_DestroyTypographyHandler(typographyHandler);
//       OH_Drawing_DestroyFontCollection(fontCollection);
//       OH_Drawing_DestroyTypographyStyle(typographyStyle);
//       OH_Drawing_DestroyTextStyle(style);
    }

    // do layout
    auto typography = OH_Drawing_CreateTypography(typographyHandler);
    OH_Drawing_TypographyLayout(typography, 300);

    auto width = OH_Drawing_TypographyGetMaxIntrinsicWidth(typography); // to make sure content has enough space
    auto height = OH_Drawing_TypographyGetHeight(typography);

    napi_value array;
    st = napi_create_array_with_length(env, 2, &array);

    napi_value num0;
    st = napi_create_double(env, ceil(width), &num0);
    st = napi_set_element(env, array, 0, num0);

    napi_value num1;
    st = napi_create_double(env, height, &num1);
    st = napi_set_element(env, array, 1, num1);
//     OH_LOG_Print(LOG_APP, LogLevel::LOG_ERROR, 0, "MIST-SDK", "measure test=(%{public}f, %{public}f)", width, height);
    return array;
  }

  napi_value ret;
  napi_get_null(env, &ret);
  return ret;
}


static napi_value measureStyleText(napi_env env, napi_callback_info info) {
  size_t argc = 5;
  napi_value args[5];
  napi_status st = napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

  auto text = GetStringChars(env, args[0], nullptr);

  double fontsize = 0;
  st = napi_get_value_double(env, args[1], &fontsize);
  
  bool bold = false;
  st = napi_get_value_bool(env, args[2], &bold);

  double fontScale = 1;
//  st = napi_get_value_double(env, args[3], &fontScale);

  double weightScale = 1;
  st = napi_get_value_double(env, args[4], &weightScale);

  auto typographyStyle = OH_Drawing_CreateTypographyStyle();

  auto style = OH_Drawing_CreateTextStyle();
  // font
  // font-size
  OH_Drawing_SetTextStyleFontSize(style, fontsize * fontScale);
  // font-style
  OH_Drawing_SetTextStyleFontStyle(style, FONT_STYLE_NORMAL);
  OH_Drawing_SetTextStyleFontWeight(style, bold ? FONT_WEIGHT_700 : FONT_WEIGHT_400);
  OH_Drawing_TextStyleAddFontVariation(style, "wght", (bold ? 700 : 400) * weightScale);
  // line-spacing

  auto fontCollection = OH_Drawing_CreateFontCollection();
  auto typographyHandler = OH_Drawing_CreateTypographyHandler(typographyStyle, fontCollection);
  OH_Drawing_TypographyHandlerPushTextStyle(typographyHandler, style);
  OH_Drawing_TypographyHandlerAddText(typographyHandler, text);
  OH_Drawing_TypographyHandlerPopTextStyle(typographyHandler);

  // do layout
  auto typography = OH_Drawing_CreateTypography(typographyHandler);
  OH_Drawing_TypographyLayout(typography, 300);

  auto width = ceil(OH_Drawing_TypographyGetMaxIntrinsicWidth(typography)); // to make sure content has enough space
  auto height = OH_Drawing_TypographyGetHeight(typography);
  OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "MIST", "measure size=%{public}f measure=%{public}f, %{public}f txt=%{public}s", fontsize, width, height, text);

  napi_value array;
  st = napi_create_array_with_length(env, 2, &array);

  napi_value num0;
  st = napi_create_double(env, ceil(width), &num0);
  st = napi_set_element(env, array, 0, num0);

  napi_value num1;
  st = napi_create_double(env, height, &num1);
  st = napi_set_element(env, array, 1, num1);
//     OH_LOG_Print(LOG_APP, LogLevel::LOG_ERROR, 0, "MIST-SDK", "measure test=(%{public}f, %{public}f)", width, height);
  return array;


//  napi_value ret;
//  napi_get_null(env, &ret);
//  return ret;
}


ArkUI_NodeContentHandle nodeContentHandle_ = nullptr;
//ArkUI_NativeNodeAPI_1 *nodeAPI;

static napi_value CreateNativeNode(napi_env env, napi_callback_info info) {
  // napi相关处理空指针&数据越界等问题
  if ((env == nullptr) || (info == nullptr)) {
    return nullptr;
  }

  size_t argc = 1;
  napi_value args[1] = {nullptr};
  if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "Manager", "CreateNativeNode napi_get_cb_info failed");
  }

  if (argc != 1) {
    return nullptr;
  }

  // 将nodeContentHandle_指向ArkTS侧传入的nodeContent
  auto ret = OH_ArkUI_GetNodeContentFromNapiValue(env, args[0], &nodeContentHandle_);

//  nodeAPI = reinterpret_cast<ArkUI_NativeNodeAPI_1 *>(
//    OH_ArkUI_QueryModuleInterfaceByName(ARKUI_NATIVE_NODE, "ArkUI_NativeNode_API_1"));
  static ArkUI_NativeGestureAPI_1 *gestureAPI = getAPIHelper()->gestureAPI;
  static ArkUI_NativeNodeAPI_1 *nodeAPI = getAPIHelper()->nodeAPI;
  static ArkUI_NativeDialogAPI_1 *dialogAPI = getAPIHelper()->dialogAPI;

  if (nodeAPI) {
    if (nodeAPI->createNode && nodeAPI->addChild) {
      ArkUI_NodeHandle component = nodeAPI->createNode(ArkUI_NodeType::ARKUI_NODE_TEXT);
      ArkUI_AttributeItem text = {.string = "text1" };
      nodeAPI->setAttribute(component, ArkUI_NodeAttributeType::NODE_TEXT_CONTENT, &text);
      nodeAPI->resetAttribute(component, ArkUI_NodeAttributeType::NODE_TEXT_CONTENT);

      std::vector<ArkUI_NodeHandle> spans;
      for (size_t i = 0; i < 5; i++) {
        ArkUI_NodeHandle span = nodeAPI->createNode(ArkUI_NodeType::ARKUI_NODE_SPAN);
        std::stringstream ss;
        ss << "span:[" << i << "],";
        auto str = ss.str();
        ArkUI_AttributeItem value = {.string = str.c_str()};
        nodeAPI->setAttribute(span, NODE_SPAN_CONTENT, &value);
        nodeAPI->addChild(component, span);
        spans.emplace_back(span);
      }

      ArkUI_NodeHandle span = nodeAPI->createNode(ArkUI_NodeType::ARKUI_NODE_SPAN);
      std::stringstream ss;
      ss << "span:[" << -1 << "],";
      auto str = ss.str();
      ArkUI_AttributeItem value = {.string = str.c_str()};
      nodeAPI->setAttribute(span, NODE_SPAN_CONTENT, &value);
      nodeAPI->insertChildAfter(component, span, nullptr);
      spans.emplace_back(span);


      // clean 1
//      auto count = nodeAPI->getTotalChildCount(component); // count == 0
//      do {
//        nodeAPI->removeChild(component, nodeAPI->getChildAt(component, 0));
//      } while(count-- > 0);
//      // clean 2
//      for (auto span : spans) {
//        nodeAPI->removeChild(component, span);
//        nodeAPI->disposeNode(span);
//      }
//      spans.clear();
//
//      // reuse with span
//      for (size_t i = 0; i < 3; i++) {
//        ArkUI_NodeHandle span1 = nodeAPI->createNode(ArkUI_NodeType::ARKUI_NODE_SPAN);
//        std::stringstream ss;
//        ss << "reuse:[" << i << "],";
//        auto str = ss.str();
//        ArkUI_AttributeItem value = {.string = str.c_str()};
//        nodeAPI->setAttribute(span1, NODE_SPAN_CONTENT, &value);
//        nodeAPI->addChild(component, span1);
//      }
//      
//      // image span
//      auto imageSpan = nodeAPI->createNode(ArkUI_NodeType::ARKUI_NODE_IMAGE_SPAN);
//      std::string url = "https://img.alicdn.com/imgextra/i4/O1CN011blldQ2AJPJdCU3vU_!!6000000008182-0-tps-700-700.jpg";
//      ArkUI_AttributeItem attr = {.string = url.c_str()};
//      nodeAPI->setAttribute(imageSpan, ArkUI_NodeAttributeType::NODE_IMAGE_SPAN_SRC, &attr);
//      ArkUI_NumberValue size[] = {{.f32 = 20}};
//      ArkUI_AttributeItem width_attr = {.value = size, .size = 1};
//      nodeAPI->setAttribute(imageSpan, ArkUI_NodeAttributeType::NODE_WIDTH, &width_attr);
//      ArkUI_AttributeItem height_attr = {.value = size, .size = 1};
//      nodeAPI->setAttribute(imageSpan, ArkUI_NodeAttributeType::NODE_HEIGHT, &height_attr);
//      ArkUI_NumberValue alignment_num[] = {{.i32 = ArkUI_ImageSpanAlignment::ARKUI_IMAGE_SPAN_ALIGNMENT_BASELINE}};
//      ArkUI_AttributeItem alignmentAttr = {.value = alignment_num, .size = 1};
//      nodeAPI->setAttribute(imageSpan, ArkUI_NodeAttributeType::NODE_IMAGE_SPAN_VERTICAL_ALIGNMENT, &alignmentAttr);

      // crash !!!
//      ArkUI_NumberValue baselineOffset[] = {{.f32 = 4}}; 
//      ArkUI_AttributeItem baselineOffsetAttr = {.value = baselineOffset, .size = 1};
//      nodeAPI->setAttribute(imageSpan, ArkUI_NodeAttributeType::NODE_SPAN_BASELINE_OFFSET, &baselineOffsetAttr);
//      nodeAPI->addChild(component, imageSpan);


      // reuse with text
//      ArkUI_AttributeItem value = {.string = "normalText" };
//      nodeAPI->setAttribute(component, ArkUI_NodeAttributeType::NODE_TEXT_CONTENT, &value);


      // 创建C侧组件，具体请查看ArkUI api文档的Capi章节
      // component = CreateNodeHandle();
      // 将组件添加到nodeContent管理器中
      OH_ArkUI_NodeContent_AddNode(nodeContentHandle_, component);

      // component
      auto rec = gestureAPI->createTapGesture(1, 1);
      gestureAPI->setGestureEventTarget(rec,
        ArkUI_GestureEventActionType::GESTURE_EVENT_ACTION_ACCEPT,
        component,
        [](ArkUI_GestureEvent* event, void* data) {
        auto helper = getAPIHelper();
        auto dialogHandle = helper->dialogAPI->create();
        auto node = helper->nodeAPI->createNode(ArkUI_NodeType::ARKUI_NODE_TEXT);

        ArkUI_AttributeItem item = {.string = "dialog content"};
        helper->nodeAPI->setAttribute(node, ArkUI_NodeAttributeType::NODE_TEXT_CONTENT, &item);

        ArkUI_NumberValue value[] = {{.f32 = 200}};
        ArkUI_AttributeItem size = {.value = value, .size = 1};
        helper->nodeAPI->setAttribute(node, ArkUI_NodeAttributeType::NODE_WIDTH, &size);
        helper->nodeAPI->setAttribute(node, ArkUI_NodeAttributeType::NODE_HEIGHT, &size);

        ArkUI_NumberValue color[] = {{.u32 = 0xFFFFCCCC}};
        ArkUI_AttributeItem bgColor = {.value = color, .size = 1};
        helper->nodeAPI->setAttribute(node, ArkUI_NodeAttributeType::NODE_BACKGROUND_COLOR, &bgColor);

        auto closeRec = helper->gestureAPI->createTapGesture(1, 1);
        helper->gestureAPI->setGestureEventTarget(closeRec,
          ArkUI_GestureEventActionType::GESTURE_EVENT_ACTION_ACCEPT,
          dialogHandle,
          [](ArkUI_GestureEvent* event, void* data){
            auto ret = getAPIHelper()->dialogAPI->close(static_cast<ArkUI_NativeDialogHandle>(data));
            ret;
          });
        helper->gestureAPI->addGestureToNode(node, closeRec, ArkUI_GesturePriority::NORMAL, ArkUI_GestureMask::NORMAL_GESTURE_MASK);

        dialogAPI->setContent(dialogHandle, node);
        dialogAPI->enableCustomStyle(dialogHandle, true);
        dialogAPI->show(dialogHandle, true);
      });
      auto ret = gestureAPI->addGestureToNode(component, rec, ArkUI_GesturePriority::NORMAL, ArkUI_GestureMask::NORMAL_GESTURE_MASK);
    }
  }

  napi_value value;
  napi_get_undefined(env, &value);
  return value;
}

void functionRValueTest();

class WatcherObject {
public:
  WatcherObject() {
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "WatcherObject", "FUNTEST::WatcherObject created instance=%{public}p lld=%{public}lld", this, this);
  }
  ~WatcherObject() {
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "WatcherObject", "FUNTEST::WatcherObject deleted instance=%{public}p lld=%{public}lld", this, this);
  }
};

void finalize_cb(napi_env env, void* p, void* ctx) {
  OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "WatcherObject", "FUNTEST::finalize invoked. will delete instance=%{public}p", p);
  auto handle = reinterpret_cast<WatcherObject*>(p);
  delete handle;
}

napi_ref targetRef = nullptr;

void call_js_cb(napi_env env, napi_value js_function, void*, void*) {
  OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "WatcherObject", "FUNTEST::tsfn invoked");
  napi_status st = napi_ok;
  
  napi_value host;
  st = napi_get_reference_value(env, targetRef, &host);
  napi_value syncCallRet;
  napi_value argv[1];
  auto watcher = new WatcherObject();
  st = napi_create_bigint_uint64(env, (uint64_t) watcher, &(argv[0]));
  st = napi_call_function(env, host, js_function, 1, argv, &syncCallRet);

  st = napi_add_finalizer(env, syncCallRet, watcher, finalize_cb, nullptr, nullptr);
  OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "napi_call_function", "FUNTEST::tsfn add finalizer success=%{public}d watcher=%{public}lld", st, (uint64_t) watcher);
}

void thread_finalize_cb(napi_env env, void* p, void* ctx) {
}

napi_threadsafe_function tsfn = nullptr;

static napi_value InitTestNapiCallFunction(napi_env env, napi_callback_info info) {
  if ((env == nullptr) || (info == nullptr)) {
    return nullptr;
  }

  size_t argc = 3;
  napi_value args[3] = {};
  if (napi_get_cb_info(env, info, &argc, args, nullptr, nullptr) != napi_ok) {
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "napi_call_function", "FUNTEST::napi_call_function init fail.");
  }

  napi_status st;
  if (!targetRef) {
    st = napi_create_reference(env, args[0], 1, &targetRef);
  }
  napi_value funcName;
  napi_value funcValue;

  auto namestr = "invokeFromNapi";
  st = napi_create_string_utf8(env, namestr, strlen(namestr), &funcName);
  st = napi_get_property(env, args[0], funcName, &funcValue);

  if (!tsfn) {
    st = napi_create_threadsafe_function(env, funcValue, args[0], funcName, 5, 1, nullptr,
                                         thread_finalize_cb, nullptr,
                                         call_js_cb, &tsfn);
  }

  size_t retry = 1; // leak occur if retry > 2
  for (auto i = 0; i < retry; i++) {
    auto watcher = new WatcherObject();
    napi_value targetValue;
    napi_value syncCallRet;
    napi_value argv[1];
    st = napi_create_bigint_uint64(env, (uint64_t) watcher, &(argv[0]));
    st = napi_get_reference_value(env, targetRef, &targetValue);
    st = napi_call_function(env, targetValue, funcValue, 1, argv, &syncCallRet);
  
    st = napi_add_finalizer(env, syncCallRet, watcher, finalize_cb, nullptr, nullptr);
    OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "napi_call_function", "FUNTEST::add finalizer success=%{public}d watcher=%{public}lld env=%{public}p", st, (uint64_t) watcher, env);
  
    st = napi_call_threadsafe_function(tsfn, nullptr, napi_threadsafe_function_call_mode::napi_tsfn_nonblocking);
  }
  
  napi_value result;
  st = napi_get_undefined(env, &result);
  return result;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
  OH_LOG_ERROR(LogType::LOG_APP, "napi_test_ init invoked!!");
  napi_property_descriptor desc[] = {
    {"add", nullptr, Add, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"measureText", nullptr, measureText, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"measureStyleText", nullptr, measureStyleText, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"createNativeNode", nullptr, CreateNativeNode, nullptr, nullptr, nullptr, napi_default, nullptr},
    {"initNapiFunctions", nullptr, InitTestNapiCallFunction, nullptr, nullptr, nullptr, napi_default, nullptr}
  };
  napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);

  functionRValueTest();
  return exports;
}
EXTERN_C_END

static napi_module demoModule = {
  .nm_version = 1,
  .nm_flags = 0,
  .nm_filename = nullptr,
  .nm_register_func = Init,
  .nm_modname = "entry",
  .nm_priv = ((void *)0),
  .reserved = {0},
};

void functionTest() {
  void* testConditionVariable = nullptr;
  void* ret = 1 == 1 ? nullptr : testConditionVariable;
}

class TObject {
  std::unordered_map<std::string, std::shared_ptr<TObject>> value;
public:
  TObject(const std::unordered_map<std::string, std::shared_ptr<TObject>>&& value): value(std::move(value)) {}
  TObject(const std::unordered_map<std::string, std::shared_ptr<TObject>>& value): value(std::move(value)) {}
};

std::shared_ptr<TObject> makeObjectMove(const std::unordered_map<std::string, std::shared_ptr<TObject>>& value) {
  return std::make_shared<TObject>(std::move(value));
}
std::shared_ptr<TObject> makeObject(const std::unordered_map<std::string, std::shared_ptr<TObject>>& value) {
  return std::make_shared<TObject>(std::move(value));
}

void functionRValueTest() {
  OH_HiTrace_StartTrace("functionRValueTest");
  std::unordered_map<std::string, std::shared_ptr<TObject>> map = {};
  for (auto i = 0; i < 2000; i++) {
    std::stringstream ss;
    ss << "key_" << i;
    map[ss.str()] = std::make_shared<TObject>(std::unordered_map<std::string, std::shared_ptr<TObject>>());
  }
  
  auto a = map;
  OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "Manager", "RValue Test a.addr=%{public}p map.addr=%{public}p", &a, &map);

  OH_HiTrace_StartTrace("mapCopyTest1");
  auto obj1 = makeObject(a);
  OH_HiTrace_FinishTrace();

  OH_HiTrace_StartTrace("mapCopyTest2");
  auto obj2 = makeObjectMove(a);
  OH_HiTrace_FinishTrace();

  auto c = obj1.use_count() + obj2.use_count();

//  for (auto i = 0; i < 2000; i++) {}
//  auto ret = makeObject(std::move(map));
//  auto c = ret.use_count();
  OH_HiTrace_FinishTrace();
  OH_LOG_Print(LOG_APP, LOG_ERROR, 0x0, "Manager", "RValue Test useCount=%{public}ld", c);
}

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) {
  OH_LOG_ERROR(LogType::LOG_APP, "RegisterEntryModule invoked!!");
  napi_module_register(&demoModule);
}


